package com.dhl.fin.api.service;

//import com.dhl.fin.api.common.config.WebConfig;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.stream.Stream;

/**
 * Author: yuayuan
 * Email:  ityuan.yuan@dhl.com
 * Date:   11/6/2019
 * Description:
 */
@Component
public class LdapAuthenticationService {

    private static Hashtable<String, String> HashEnv;

    private static  String[] attributeToSearch = {"employeeNumber", "displayName", "mail"};

    private static Log logger = LogFactory.getLog(LdapAuthenticationService.class);

//    private static WebConfig config;

    @Autowired
//    public LdapAuthenticationService(WebConfig config) {
//        this.config = config;
//    }

    public LdapAuthenticationService() {
    }

    private static void init(){
        HashEnv = new Hashtable<>();
        HashEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); // LDAP访问安全级别(none,simple,strong)
        HashEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // LDAP工厂类
//        HashEnv.put(Context.PROVIDER_URL, "ldap://" + config.ldapHost + ":" + config.ldapPost + "/");
//        HashEnv.put(Context.PROVIDER_URL, "ldap://ads.cn.dhl.com:389/");
        HashEnv.put("com.sun.jndi.ldap.connect.timeout", "500");
    }

    public static boolean auth(String username, String password) throws NamingException {
        DirContext ctx = null;
        if (HashEnv == null) {
            init();
        }
        HashEnv.put(Context.SECURITY_PRINCIPAL, "kul-dc\\" + username); // AD的用户名
        HashEnv.put(Context.SECURITY_CREDENTIALS, password); // AD的密码
        try {
            ctx = new InitialDirContext(HashEnv);// 初始化上下文
            LdapAuthenticationService auth = new LdapAuthenticationService();

            auth.search(ctx, username).forEach(sarr -> Stream.of(sarr).forEach(System.out::println));

            //logger.info(ctx.getAttributes("name")+"-----------------------");
            return true;
        } catch (AuthenticationException e) {
            logger.error("身份验证失败!");
            throw e;
        } catch (javax.naming.CommunicationException e) {
            logger.error("AD域连接失败!", e);
            throw e;
        } catch (Exception e) {
            logger.error("身份验证未知异常!", e);
            throw e;
        } finally {
            if (null != ctx) {
                try {
                    ctx.close();
                } catch (Exception e) {
                    logger.error(e);
                }
            }
        }
    }

    @SuppressWarnings("unused")
    private List<String[]> search(DirContext ctx, String userid) {
        List<String[]> result = new ArrayList<>();
        SearchControls constraints = new SearchControls();
        constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
        constraints.setReturningAttributes(attributeToSearch);
        String filter = "cn=" + userid;
        String userBase = "OU=CN,DC=kul-dc,DC=dhl,DC=com";

        NamingEnumeration<SearchResult> results;
        try {
            results = ctx.search(userBase, filter, constraints);
            while (results != null) {
                SearchResult entry;
                try {
                    entry = results.nextElement();
                } catch (Exception e) {
                    break;
                }
                if (entry == null)
                    continue;
                String[] line = new String[attributeToSearch.length + 1];
                line[0] = entry.getName();
                for (int i = 1; i <= attributeToSearch.length; i++) {
                    NamingEnumeration<?> attr;
                    try {
                        attr = entry.getAttributes().get(attributeToSearch[i - 1]).getAll();
                    } catch (Exception e) {
                        continue;
                    }
                    while (attr.hasMore()) {
                        if (line[i] != null)
                            line[i] = line[i] + ";" + attr.next().toString();
                        else
                            line[i] = attr.next().toString();
                    }
                    line[i] = entry.getAttributes().get(attributeToSearch[i - 1]).getAll().next().toString();
                }
                result.add(line);
            }
        } catch (NamingException e1) {
            e1.printStackTrace();
        }
        return result;
    }
}
